import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.LinkedList;



public abstract class Ball {

	protected int name;
	protected LinkedList<GregorianCalendar> dates;
	protected long odd;
	protected LinkedList<Integer> daysInBetween;
	protected ThreeDMatrix threeDMatrix;
	protected FourDMatrix fourDMatrix;
	protected FiveDMatrix fiveDMatrix;
	
	public static void main(String[] args)
	{
		GregorianCalendar date1 = new GregorianCalendar(2011, 11, 31);
		GregorianCalendar date2 = new GregorianCalendar(2012, 0, 2);
		Ball b = new MainBall(1);
		System.out.println(b.daysBetween(date2, date1));
	}
	/*
	public void addDate(int y, int m, int d)
	{
		GregorianCalendar temp = new GregorianCalendar(y, m-1, d);
		if(temp.get(Calendar.DAY_OF_WEEK) == Calendar.TUESDAY)
		{
			temp.set(Calendar.HOUR, 21);
			temp.set(Calendar.MINUTE, 30);
		}
		else
		{
			temp.set(Calendar.HOUR, 23);
			temp.set(Calendar.MINUTE, 30);
		}
		dates.add(temp);
		System.out.println(temp.getTime());
	}*/
	
	/*public void addAndDisplayDate(int y, int m, int d)
	{
		GregorianCalendar temp = new GregorianCalendar(y, m-1, d);
		if(temp.get(Calendar.DAY_OF_WEEK) == Calendar.TUESDAY)
		{
			temp.set(Calendar.HOUR, 21);
			temp.set(Calendar.MINUTE, 30);
		}
		else
		{
			temp.set(Calendar.HOUR, 23);
			temp.set(Calendar.MINUTE, 30);
		}
		System.out.println(temp.getTime());
	}*/
	
	
	public void addDate(GregorianCalendar date)
	{	
		GregorianCalendar temp = new GregorianCalendar();
		temp.setTimeInMillis(date.getTimeInMillis());
		if(temp.get(Calendar.DAY_OF_WEEK) == Calendar.TUESDAY)
		{
			temp.set(Calendar.HOUR, 21);
			temp.set(Calendar.MINUTE, 30);
		}
		else
		{
			temp.set(Calendar.HOUR, 23);
			temp.set(Calendar.MINUTE, 30);
		}
		dates.add(temp);
	}
	
	public LinkedList<GregorianCalendar> getDates()
	{
		return dates;
	}
	
	public int getName()
	{
		return name;
	}
	
	public int getOccurance(int day)
	{
		int result = 0;
		for(GregorianCalendar cal: dates)
		{
			if (cal.get(GregorianCalendar.DAY_OF_WEEK) == day) {
				result++;
			}
		}
		return result;
	}
	
	public void addOdd(long i)
	{
		odd += i;
	}
	
	public long getOdd()
	{
		return odd;
	}
	
	public int daysBetween(GregorianCalendar calendar, GregorianCalendar calendar2)
	{
		GregorianCalendar replica1 = (GregorianCalendar) calendar.clone();
		GregorianCalendar replica2 = (GregorianCalendar) calendar2.clone();
		int result = -100;
		if(replica1.equals(replica2))
		{
			result = 0;
		}
		else if(replica1.after(replica2))
		{
			//System.out.println(calendar.getTime() + " is after " + calendar2.getTime());
			if(replica1.get(Calendar.YEAR) == replica2.get(Calendar.YEAR))
			{
				int val1 = replica1.get(Calendar.DAY_OF_YEAR);
				int val2 = replica2.get(Calendar.DAY_OF_YEAR);
				result = val1 - val2;
			}
			else
			{
				int days = 0;
				while(replica2.get(Calendar.YEAR) < replica1.get(Calendar.YEAR))
				{
					days++;
					replica2.add(Calendar.DAY_OF_YEAR, 1);
				}
			
				while(replica2.get(Calendar.DAY_OF_YEAR) < replica1.get(Calendar.DAY_OF_YEAR))
				{
					days++;
					replica2.add(Calendar.DAY_OF_YEAR, 1);
				}
				result = days;
			}
		}
		
		else
		{
			//System.out.println(calendar.getTime() + " is before " + calendar2.getTime());
			if(replica1.get(Calendar.YEAR) == replica2.get(Calendar.YEAR))
			{
				int val1 = replica1.get(Calendar.DAY_OF_YEAR);
				int val2 = replica2.get(Calendar.DAY_OF_YEAR);
				result = val1 - val2;
			}
			else
			{
				int days = 0;
				while(replica1.get(Calendar.YEAR) < replica2.get(Calendar.YEAR))
				{
					days++;
					replica1.add(Calendar.DAY_OF_YEAR, 1);
				}
			
				while(replica1.get(Calendar.DAY_OF_YEAR) < replica2.get(Calendar.DAY_OF_YEAR))
				{
					days++;
					replica1.add(Calendar.DAY_OF_YEAR, 1);
				}
				result = days * -1;
			}
		}
		return result;
	}
	
	public void processDates(GregorianCalendar c)
	{
		for(int i = 0; i < dates.size()-1; i++)
		{
			this.daysInBetween.add(Math.abs(daysBetween(dates.get(i), dates.get(i+1))));
			//System.out.println(daysBetween(dates.get(i), dates.get(i+1)));
		}
		daysInBetween.add(Math.abs(daysBetween(dates.getLast(), c)));
	}
	
	/*public int partition(LinkedList<Calendar> list, int left, int right)
	{
		int i = left, j = right;
		Calendar temp;
		long pivot = list.get((left + right)/2).getTimeInMillis();
		while(i <= j)
		{
			while(list.get(i).getTimeInMillis() < pivot)
			{
				i++;
			}
			while(list.get(j).getTimeInMillis() > pivot)
			{
				j--;
			}
			if(i <= j)
			{
				temp = list.get(i);
				list.set(i, list.get(j));
				list.set(j, temp);
				i++;
				j--;
			}
		}
		return i;
	}*/
	
	public int getOddBasedOnDates()
	{
		int result = -100;
		int temp = 0;
		for(int inbetween: daysInBetween)
		{
			temp = (temp + inbetween)/3*2;
		}
		result = temp;
		return result;
	}
	
	/*
	public void quickSort(LinkedList<Calendar> list, int left, int right)
	{
		int index = partition(list, left, right);
		if(left < index -1)
		{
			quickSort(list, left, index-1);
		}
		if(index < right)
		{
			quickSort(list, index, right);
		}
	}
	
	public void sortDates()
	{
		quickSort(this.dates, 0, dates.size()-1);
	}*/
	
	public void processThreeD(int day)
	{
		for(GregorianCalendar cal: dates)
		{
			if(cal.get(GregorianCalendar.DAY_OF_WEEK) == day)
			{
				this.threeDMatrix.data.add(cal.getTimeInMillis());
			}
		}
		this.threeDMatrix.process();
	}
	
	public ThreeDMatrix getThreeDMatrix()
	{
		return this.threeDMatrix;
	}
	
	public void processFourD()
	{
		for(GregorianCalendar gc: dates)
		{
			this.fourDMatrix.getDatas().add(gc);
		}
		this.fourDMatrix.process();
	}
	
	public FourDMatrix getFourDMatrix()
	{
		return this.fourDMatrix;
	}
	
	public void processFiveD(int day)
	{
		for(GregorianCalendar gc: dates)
		{
			if(gc.get(GregorianCalendar.DAY_OF_WEEK) == day)
			{
				this.fiveDMatrix.data.add(gc.getTimeInMillis());
			}
		}
		this.fiveDMatrix.process();
	}
	
	public FiveDMatrix getFiveDMatrix()
	{
		return this.fiveDMatrix;
	}
}
